﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Xml;

namespace NugetSlnCacheCleaner
{
	class Program
	{

		/// <summary>
		/// 引用列表，string format：Assembly.version
		/// </summary>
		static List<string> referenceList = new List<string>();
		static List<string> configFiles = new List<string>();


		static void Main(string[] args)
		{
			clearSlnNugetCache();
		}

		private static void clearSlnNugetCache()
		{
			//检查条件，是否存在packages文件夹，如果不存在就结束任务
			const string packages = "packages";
			const string slnPackages = ".nuget\\packages.config";
			if (!Directory.Exists(packages)) return;

			//检查解决方案文件夹的.nuget文件夹下的引用列表,如果存在的话
			var slnPackagesPath = Path.Combine(Environment.CurrentDirectory, slnPackages);
			if (File.Exists(slnPackagesPath))
				buildReferenceList(slnPackagesPath);

			//设置当前工作目录：packages文件夹
			Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, packages);

			//检查条件，是否存在repositories.config文件，如果不存在就结束任务
			const string repositories = "repositories.config";
			if (!File.Exists(repositories)) return;

			XmlDocument xd = new XmlDocument();
			xd.Load(repositories);

			foreach (XmlNode xn in xd.ChildNodes)
				if (xn.NodeType == XmlNodeType.Element)
					foreach (XmlNode xnc in xn.ChildNodes)
						buildReferenceList(xnc.Attributes["path"].Value);
			//此时，引用列表创建完毕

			//检测是否存在丢失配置文件的情况，如果有给出提示，并退出程序
			if (configFiles.Count > 0)
			{
				//显示配置文件丢失情况
				StringBuilder sb = new StringBuilder();
				foreach (var filepath in configFiles) sb.AppendLine(filepath);
				Microsoft.VisualBasic.Interaction.MsgBox("This(These) config file(s) was(were) lost:\n\n" + sb.ToString() + "\nSo, we did nothing!", Microsoft.VisualBasic.MsgBoxStyle.Exclamation & Microsoft.VisualBasic.MsgBoxStyle.OkOnly, "warning");
			}
			else
			{
				//删除多余的库文件夹
				int deleteCount = 0;
				foreach (string dir in Directory.GetDirectories(Environment.CurrentDirectory))
				{
					//跳过已引用的库文件夹
					if (referenceList.Contains(Path.GetFileName(dir).ToLower())) continue;
					Microsoft.VisualBasic.FileIO.FileSystem.DeleteDirectory(dir, Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs, Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin);
					deleteCount++;
				}

				//显示统计结果
				Microsoft.VisualBasic.Interaction.MsgBox("Total clean count: " + deleteCount, Microsoft.VisualBasic.MsgBoxStyle.Information & Microsoft.VisualBasic.MsgBoxStyle.OkOnly, "information");
			}
		}

		/// <summary>
		/// 构建引用列表
		/// </summary>
		/// <param name="path">记录引用的文件路径</param>
		static void buildReferenceList(string path)
		{
			//引用文件不存在就直接返回
			if (!File.Exists(path))
			{
				configFiles.Add(path);
				return;
			}
			var xd = System.Xml.Linq.XDocument.Load(path);

			var names = from node in xd.Element("packages").Elements()
						select (node.Attribute("id").Value.ToLower() + "." + node.Attribute("version").Value.ToLower());
			referenceList.AddRange(names);
		}
	}
}
